const c = {
  events: {},
  publish: function(t, e) {
    this.events.hasOwnProperty(t) && this.events[t].forEach((n) => n(e));
  },
  subscribe: function(t, e) {
    return this.events.hasOwnProperty(t) || (this.events[t] = []), this.events[t].push(e), {
      unsubscribe: (function() {
        const n = this.events[t].indexOf(e);
        n !== -1 && this.events[t].splice(n, 1);
      }).bind(this)
    };
  }
}, o = {
  CONNECT: {
    NATIVE: "gamepadconnected",
    ALIAS: "connect"
  },
  DISCONNECT: {
    NATIVE: "gamepaddisconnected",
    ALIAS: "disconnect"
  },
  BUTTON_PRESS: {
    ALIAS: "button_press"
  },
  BUTTON_RELEASE: {
    ALIAS: "button_release"
  },
  AXIS_MOVEMENT: {
    ALIAS: "axis_move"
  }
}, S = {
  button_0: 0,
  button_1: 1,
  button_2: 2,
  button_3: 3,
  button_4: 4,
  button_5: 5,
  button_6: 6,
  button_7: 7,
  button_8: 8,
  button_9: 9,
  button_10: 10,
  button_11: 11,
  button_12: 12,
  button_13: 13,
  button_14: 14,
  button_15: 15,
  button_16: 16,
  button_17: 17
}, f = 0.8, E = (t) => {
  console.warn && typeof console.warn == "function" ? console.warn(t) : console.log(t);
}, h = (t, e) => {
  let n = [];
  return Object.keys(e).forEach((s) => {
    (e[s] === t || Array.isArray(e[s]) && e[s].indexOf(t) !== -1) && n.push(s);
  }), n;
}, T = (t) => !!(t && t.type && t.playEffect && typeof t.playEffect == "function"), I = () => !!(window.navigator.getGamepads && typeof window.navigator.getGamepads == "function"), d = {
  loopStarted: !1,
  instances: {},
  buttonEvents: {
    joypad: []
  },
  settings: {
    axisMovementThreshold: f
  },
  remove: function(t) {
    return delete this.instances[t];
  },
  on: function(t, e) {
    switch (t) {
      case o.CONNECT.ALIAS:
        return c.subscribe(o.CONNECT.ALIAS, e);
      case o.DISCONNECT.ALIAS:
        return c.subscribe(o.DISCONNECT.ALIAS, e);
      case o.BUTTON_PRESS.ALIAS:
        return c.subscribe(o.BUTTON_PRESS.ALIAS, e);
      case o.BUTTON_RELEASE.ALIAS:
        return c.subscribe(o.BUTTON_RELEASE.ALIAS, e);
      case o.AXIS_MOVEMENT.ALIAS:
        return c.subscribe(o.AXIS_MOVEMENT.ALIAS, e);
    }
  },
  vibrate: function(t, e) {
    const { vibrationActuator: n } = t, s = e || this.settings.vibration;
    if (T(n)) {
      const { type: a } = n;
      return t.vibrationActuator.playEffect(a, s);
    } else
      E("No vibration actuator interface found - https://developer.mozilla.org/en-US/docs/Web/API/GamepadHapticActuator");
  },
  set: function(t) {
    const { axisMovementThreshold: e, vibration: n, customButtonMapping: s } = t, a = parseFloat(e);
    isNaN(a) || (this.settings.axisMovementThreshold = a), this.settings.vibration = n, this.settings.customButtonMapping = s;
  },
  trigger: function(t, e) {
    return c.publish(t, e);
  }
}, A = {
  id: null,
  start: function() {
    const t = window.requestAnimationFrame || window.webkitRequestAnimationFrame, { buttonEvents: e } = d;
    let n = window.navigator.getGamepads();
    n = Array.prototype.slice.call(n), n.forEach((s, a) => {
      s && (e.joypad[a] || (e.joypad[a] = {}), d.instances[a] = s, w(s), L(s));
    }), e.joypad.forEach((s) => {
      s && Object.keys(s).forEach((a) => {
        N(a, s);
      });
    }), this.id = t(this.start.bind(this));
  },
  stop: function(t) {
    return (window.cancelAnimationFrame || window.webkitCancelAnimationFrame)(t);
  }
}, _ = () => {
  window.addEventListener(o.CONNECT.NATIVE, (t) => {
    if (c.publish(o.CONNECT.ALIAS, t), !d.loopStarted)
      return d.loopStarted = !0, A.start();
  }), window.addEventListener(o.DISCONNECT.NATIVE, (t) => {
    if (c.publish(o.DISCONNECT.ALIAS, t), d.remove(t.gamepad.index), d.buttonEvents.joypad[t.gamepad.index] = null, !Object.keys(d.instances).length)
      return d.loopStarted = !1, A.stop(A.id);
  }), window.addEventListener(o.BUTTON_PRESS.ALIAS, (t) => c.publish(o.BUTTON_PRESS.ALIAS, t)), window.addEventListener(o.BUTTON_RELEASE.ALIAS, (t) => c.publish(o.BUTTON_RELEASE.ALIAS, t)), window.addEventListener(o.AXIS_MOVEMENT.ALIAS, (t) => c.publish(o.AXIS_MOVEMENT.ALIAS, t));
}, w = (t) => {
  t.buttons.forEach((e, n) => {
    const { customButtonMapping: s } = d.settings, u = h(n, s || S), { buttonEvents: i } = d;
    u && u.length && u.forEach((r) => {
      e.pressed ? (i.joypad[t.index][r] || (i.joypad[t.index][r] = {
        pressed: !0,
        hold: !1,
        released: !1
      }), i.joypad[t.index][r].button = e, i.joypad[t.index][r].index = n, i.joypad[t.index][r].gamepad = t) : !e.pressed && i.joypad[t.index][r] && (i.joypad[t.index][r].released = !0, i.joypad[t.index][r].hold = !1);
    });
  });
};
let l = [0, 0, 0, 0];
const b = (t) => {
  if (!l) return !0;
  const e = 0.05;
  for (let n = 0; n < t.length; n++)
    if (Math.abs(t[n] - l[n]) > e)
      return !0;
  return !1;
}, L = (t) => {
  const e = (i) => new CustomEvent(o.AXIS_MOVEMENT.ALIAS, { detail: i }), s = t.axes.map((i) => {
    const r = Number(i.toFixed(4));
    return Math.abs(r) < 1e-4 ? 0 : r;
  }), u = s.length / 2;
  if (b(s)) {
    let i = "stick_moved";
    l = s;
    const r = { gamepad: t, totalSticks: u, stickMoved: i, axes: s };
    return window.dispatchEvent(e(r));
  }
}, p = (t, e, n) => {
  const s = (r) => new CustomEvent(t, { detail: r }), { index: a, gamepad: u } = e[n], i = {
    buttonName: n,
    button: e[n].button,
    index: a,
    gamepad: u
  };
  window.dispatchEvent(s(i));
}, N = (t, e) => {
  e[t].pressed ? (p(o.BUTTON_PRESS.ALIAS, e, t), e[t].pressed = !1, e[t].hold = !0, e[t].last_event = o.BUTTON_PRESS.ALIAS) : e[t].hold || e[t].released && e[t].last_event === o.BUTTON_PRESS.ALIAS && (p(o.BUTTON_RELEASE.ALIAS, e, t), delete e[t]);
};
_();
I() ? window.joypad = d : (window.joypad = {}, E("Your browser does not support the Gamepad API - https://developer.mozilla.org/en-US/docs/Web/API/Gamepad_API"));
